package com.faceye.core.service.impl;

import com.faceye.core.util.Json;
import org.apache.commons.collections.MapUtils;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.util.*;

/**
 * @Description:
 * @Author:haipenge
 * @Date:2020-07-17 14:47
 * @Version:1.0
 **/
@Component
public class CacheKeyGenerator implements KeyGenerator {
    private String keyPrefix="PAGE";
    private String sp=":";
    @Override
    public Object generate(Object target, Method method, Object... params) {
        StringBuilder key=new StringBuilder();
        key.append(keyPrefix);
        key.append(sp);
        key.append(target.getClass().getSimpleName());
        key.append(sp);
        key.append(method.getName());
        key.append(sp);
        if(params!=null && params.length>0){
            for(Object param:params){
                if(param!=null) {
                    if (isSimpleValueType(param.getClass())) {
                        key.append(param);
                    } else {
                        if (param instanceof Map) {
                            key.append(buildMapKey((Map) param));
                        } else {
                            key.append(Json.toJson(param));
                        }
                    }
                }
            }
        }else{
            key.append("NO_PARAM_KEY");
        }
//        char[] chrs=key.toString().toCharArray();
//        Object [] objs=new Object[]{chrs};
//        return Arrays.deepHashCode(objs);
        return key.toString();
    }


    private static boolean isSimpleValueType(Class<?> clazz) {
        return (ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.isEnum() || CharSequence.class.isAssignableFrom(clazz)
                || Number.class.isAssignableFrom(clazz) || Date.class.isAssignableFrom(clazz) || URI.class == clazz
                || URL.class == clazz || Locale.class == clazz || Class.class == clazz);

    }

    private String buildMapKey(Map map){
        StringBuilder key=new StringBuilder();
        if(MapUtils.isNotEmpty(map)) {
            TreeMap treeMap = new TreeMap();
            treeMap.putAll(map);
            Iterator it= treeMap.keySet().iterator();
            while(it.hasNext()){
                Object k=it.next();
                Object v= treeMap.get(k);
                if(v!=null){
                    key.append(k);
                    key.append(v);
                }
            }
        }

        return key.toString();
    }



}
